package org.feng.navigation.rest.gatewayimpl;

import lombok.Getter;
import lombok.extern.slf4j.Slf4j;
import org.feng.navigation.domain.rpc.common.Router;

import javax.annotation.PostConstruct;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.Map;

/**
 * 路由工厂类
 *
 * @version v1.0
 * @author: junzi
 * @date: 2023年02月05日 15时04分
 */
@Slf4j
public abstract class RouterFactory {

    @Getter
    protected Map<Class<?>, Method> routerMethodMap;

    public RouterFactory() {
        routerMethodMap = new HashMap<>(16);
    }

    @PostConstruct
    private void init() {
        Method[] declaredMethods = this.getClass().getDeclaredMethods();
        for (Method declaredMethod : declaredMethods) {
            if (declaredMethod.isAnnotationPresent(Router.class)) {
                Router router = declaredMethod.getAnnotation(Router.class);
                routerMethodMap.put(router.value(), declaredMethod);
            }
        }
        // 记录日志
        routerMethodMap.forEach((key, value) -> {
            log.info("初始化路由：key={}, value={}", key.getSimpleName(), value.getName());
        });
    }

    /**
     * 在子类中，定义多个方法，使用Router注解表示不同的业务处理
     *
     * @param businessParam 业务参数对象
     * @param resultClass   需要转换的响应类型
     * @param <T>           响应类型
     * @return 响应结果
     */
    @SuppressWarnings("all")
    public <T> T execute(Object businessParam, Class<T> resultClass) {
        Method method = routerMethodMap.get(businessParam.getClass());
        Object result;
        try {
            method.setAccessible(true);
            result = method.invoke(this, businessParam);
        } catch (IllegalAccessException | InvocationTargetException e) {
            throw new RuntimeException(e);
        }
        return (T) result;
    }
}
